/**
*  \file fd.h
*
*  \brief   Generic file handle interface.
*
*  \author   Michael J. Hohmann <michael.hohmann@linde-mh.de>
*  \author   Michael Kunkelmann <m.kunkelmann@webergmbh.de>
*
*
*/

#ifndef FD_H_INCLUDED
#define FD_H_INCLUDED

/*================================================[ public includes  ]================================================*/
#include "../cfg/prj.h"
#include "../cfg/fd_cfg.h"

/*================================================[ public defines   ]================================================*/

#define FD_SEEK_SET  0
#define FD_SEEK_CUR  1
#define FD_SEEK_END  2

/*================================================[ public datatypes ]================================================*/

/* Forward declaration. */
struct fd;


/** File device property object. */
struct fd_property
{
   U32 size;                        /**< Object size. */
   U32 modified_date;               /**< Object last modified. */
#if (FD_USE_FILENAME == 1)
   CH name[FD_FILENAME_MAX_SIZE];   /**< Object name. */
#endif
};


/** File device access mode. */
enum fd_access_mode
{
   fd_access_mode_read       = 0,   /**< File device is read only. */
   fd_access_mode_write      = 1,   /**< File device is write only. */
   fd_access_mode_read_write = 2,   /**< File device has read/write access. */
   fd_access_mode_append     = 3    /**< File device can be appended. */
};


/** File device close status mode */
enum fd_close_status
{
   fd_close_status_success = 0,  /**< File close status was successfully. */
   fd_close_status_abort   = 1   /**< File was closed due to an error. */
};


/** File device status indication. */
enum fd_status
{
   fd_status_closed = 1,   /**< File device was closed. */
   fd_status_opened = 2,   /**< File device was opened. */
   fd_status_read   = 3,   /**< Data are read from file device. */
   fd_status_write  = 4    /**< Data are written to file device. */
};


/** File device status. */
struct fd_stat
{
   enum fd_status status;        /**< Actual status of the file device. */
   enum fd_access_mode access;   /**< File device access mode. */
   U32 size_min;                 /**< Minimum size of the file device data. */
   U32 size_max;                 /**< Maximum size of the file device data. */
   U32 size;                     /**< Actual size of the file device data. */
   U32 position;                 /**< Actual position in the file device object. */
   U32 modify_date;              /**< File device modified date. */
#if (FD_USE_FILENAME == 1)
   CH name[FD_FILENAME_MAX_SIZE];   /**< Object name. */
#endif
};


/** File device open callback. */
typedef RC (*fd_open_function_t) ( struct fd *me, CH* mode );

/** File device read callback. */
typedef RC (*fd_read_function_t) ( struct fd *me, void *data, U32 size );

/** File device write callback. */
typedef RC (*fd_write_function_t)( struct fd *me, void const* data, U32 size );

/** File device set callback. */
typedef RC (*fd_set_function_t)( struct fd *me, U8 value, U32 size );

/** File device seek callback. */
typedef RC (*fd_seek_function_t) ( struct fd *me, S32 pos, U16 whence );

/** File device get status callback. */
typedef RC (*fd_get_status_function_t) ( struct fd *me, struct fd_stat *stat );

/** File device set status callback. */
typedef RC (*fd_set_status_function_t) ( struct fd *me, struct fd_stat stat );

/** File device close callback. */
typedef RC (*fd_close_function_t)( struct fd *me, enum fd_close_status close_state );


/** File device object. */
struct fd
{
   fd_open_function_t open;               /**< File device open member function. */
   fd_read_function_t read;               /**< File device read member function. */
   fd_write_function_t write;             /**< File device write member function. */
   fd_close_function_t close;             /**< File device close member function. */
   fd_set_function_t set;                 /**< File device set member function. */
   fd_seek_function_t seek;               /**< File device seek member function. */
   fd_get_status_function_t stat;         /**< File device get status member function. */
   fd_set_status_function_t set_status;   /**< File device set status member function. */
};

/*================================================[ public variables ]================================================*/

/*================================================[ public functions ]================================================*/


/** Basic file device 'open' function.
*
*  The function fd_open() calls the overloaded 'open' member function.
*
*  \param me Pointer to the file device object. It is not save to pass NULL.
*  \param mode Pointer to the mode object. It is not save to pass NULL.
*
*  \return RC_SUCCESS if device could be opened.
*          RC_ERROR if device is not valid.
*
*/
STATIC_INLINE RC fd_open( struct fd *me, CH* mode )
{
   if(( NIL != me ) && ( NIL != me->open ))
   {
      return me->open( me, mode );
   }
   else
   {
      return RC_ERROR_NULL;
   }
}


/** Basic file device 'read' function.
*
*  The function fd_read() calls the overloaded 'read' member function.
*
*  \param me Pointer to the file device object.
*  \param data Pointer to the data to be read out of the file device. It is not save to pass NULL.
*  \param size Amount of data to be read from the file device.
*
*  \return RC_SUCCESS if data could be read from the file device.
*          RC_ERROR if device is not valid.
*
*/
STATIC_INLINE RC fd_read( struct fd *me, void *data, U32 size )
{
   if(( NIL != me ) && ( NIL != me->read ) )
   {
      return me->read( me, data, size );
   }
   else
   {
      return RC_ERROR_NULL;
   }
}


/** Basic file device 'write' function.
*
*  The function fd_write() calls the overloaded 'write' member function.
*
*  \param me Pointer to the file device object. It is not save to pass NULL.
*  \param data Pointer to the data to be written to the file device. It is not save to pass NULL.
*  \param size Amount of data to be written to the file device.
*
*  \return RC_SUCCESS if data could be written to the file device.
*          RC_ERROR if device is not valid.
*
*/
STATIC_INLINE RC fd_write( struct fd *me, void const *data, U32 size )
{
   if(( NIL != me ) && ( NIL != me->write ))
   {
      return me->write( me, data, size );
   }
   else
   {
      return RC_ERROR_NULL;
   }
}


/** Basic file device 'set' function.
*
*  The function fd_set() calls the overloaded 'set' member function.
*
*  \param me Pointer to the file device object. It is not save to pass NULL.
*  \param value Value to be set.
*  \param size Amount of data to be set within the file device.
*
*  \return RC_SUCCESS if data could be set within the file device.
*          RC_ERROR if device is not valid.
*
*/
#if 0
STATIC_INLINE RC fd_set( struct fd *me, U8 value, U32 size )
{
   if(( NIL != me ) && ( NIL != me->set ))
   {
      return me->set( me, value, size );
   }
   else
   {
      return RC_ERROR_NULL;
   }
}
#endif

/** Basic file device 'close' function.
*
*  The function fd_close() calls the overloaded 'close' member function.
*
*  \param me Pointer to the file device object. It is not save to pass NULL.
*  \param close_state
*
*  \return RC_SUCCESS if file device could be closed.
*          RC_ERROR if device is not valid.
*
*/
STATIC_INLINE RC fd_close( struct fd *me, enum fd_close_status close_state )
{
   if(( NIL != me ) && ( NIL != me->close ))
   {
      return me->close( me, close_state );
   }
   else
   {
      return RC_ERROR_NULL;
   }
}



/** Basic file device 'get status' function.
*
*  The function fd_stat() calls the overloaded 'get status' member function.
*
*  \param me Pointer to the file device object. It is not save to pass NULL.
*  \param stat Pointer to the status object. It is not save to pass NULL.
*
*  \return RC_SUCCESS if status could be read from the file device.
*          RC_ERROR if device is not valid.
*
*/
STATIC_INLINE RC fd_stat( struct fd *me, struct fd_stat *stat )
{
   if(( NIL != me ) && ( NIL != me->stat ) && ( NIL != stat ) )
   {
      return me->stat( me, stat );
   }
   else
   {
      return RC_ERROR_NULL;
   }
}


/** Basic file device 'set status' function.
*
*  The function fd_set_status() calls the overloaded 'set status' member function.
*
*  \param me Pointer to the file device object. It is not save to pass NULL.
*  \param stat Status object.
*
*  \return RC_SUCCESS if status could be written to the file device.
*          RC_ERROR if device is not valid.
*
*/
STATIC_INLINE RC fd_set_status( struct fd *me, struct fd_stat stat )
{
   if(( NIL != me ) && ( NIL != me->set_status ) )
   {
      return me->set_status( me, stat );
   }
   else
   {
      return RC_ERROR_NULL;
   }
}


/** Basic file device 'seek' function.
 *
*  The function fd_seek() calls the overloaded 'seek' member function.
*
*  \param me     Pointer to the file device object. It is not save to pass NULL.
*  \param pos    Position within file object.
*  \param whence Type
*
*  \return RC_SUCCESS if status could be written to the file device.
*          RC_ERROR if device is not valid.
*/
STATIC_INLINE RC fd_seek( struct fd *me, S32 pos, U16 whence )
{
   if(( NIL != me ) && ( NIL != me->seek ))
   {
     return me->seek( me, pos, whence );
   }
   else
   {
     return RC_ERROR_NULL;
   }
}


/*====================================================================================================================*/

#endif

/***********************************************************************************************************************
*                             Copyright 2010 Linde Material Handling. All rights reserved.                             *
***********************************************************************************************************************/
